home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Gold Collection / Software Vault - The Gold Collection (American Databankers) (1993).ISO / cdr05 / shwdib.zip / DIB.C < prev    next >
C/C++ Source or Header  |  1993-07-26  |  33KB  |  853 lines

  1. /*******************************************************************************
  2.  *                                                                             *
  3.  *  MODULE      : DIB.C                                                        *
  4.  *                                                                             *
  5.  *  DESCRIPTION : Routines for dealing with Device Independent Bitmaps.        *
  6.  *                                                                             *
  7.  *  FUNCTIONS   : OpenDIB()           - Opens DIB file and creates a memory DIB*
  8.  *                                                                             *
  9.  *                WriteDIB()          - Writes a global handle in CF_DIB format*
  10.  *                                      to a file.                             *
  11.  *                                                                             *
  12.  *                DibInfo()           - Retrieves the info. block associated   *
  13.  *                                      with a CF_DIB format memory block.     *
  14.  *                                                                             *
  15.  *                CreateBIPalette()   - Creates a GDI palette given a pointer  *
  16.  *                                      to a BITMAPINFO structure.             *
  17.  *                                                                             *
  18.  *                CreateDibPalette()  - Creates a GDI palette given a HANDLE   *
  19.  *                                      to a BITMAPINFO structure.             *
  20.  *                                                                             *
  21.  *                ReadDibBitmapInfo() - Reads a file in DIB format and returns *
  22.  *                                      a global handle to it's BITMAPINFO     *
  23.  *                                                                             *
  24.  *                PaletteSize()       - Calculates the palette size in bytes   *
  25.  *                                      of given DIB                           *
  26.  *                                                                             *
  27.  *                DibNumColors()      - Determines the number of colors in DIB *
  28.  *                                                                             *
  29.  *                BitmapFromDib()     - Creates a DDB given a global handle to *
  30.  *                                      a block in CF_DIB format.              *
  31.  *                                                                             *
  32.  *                DibFromBitmap()     - Creates a DIB repr. the DDB passed in. *
  33.  *                                                                             *
  34.  *                DrawBitmap()        - Draws a bitmap at specified position   *
  35.  *                                      in the DC.                             *
  36.  *                                                                             *
  37.  *                DibBlt()            - Draws a bitmap in CIF_DIB format using *
  38.  *                                      SetDIBitsToDevice()                    *
  39.  *                                                                             *
  40.  *                StretchDibBlt()     - Draws a bitmap in CIF_DIB format using *
  41.  *                                      StretchDIBits()                        *
  42.  *                                                                             *
  43.  *                lread()             - Private routine to read more than 64k  *
  44.  *                                                                             *
  45.  *                lwrite()            - Private routine to write more than 64k *
  46.  *                                                                             *
  47.  *******************************************************************************/
  48. // COPYRIGHT:
  49. //
  50. //   (C) Copyright Microsoft Corp. 1992.  All rights reserved.
  51. //
  52. //   You have a royalty-free right to use, modify, reproduce and
  53. //   distribute the Sample Files (and/or any modified version) in
  54. //   any way you find useful, provided that you agree that
  55. //   Microsoft has no warranty obligations or liability for any
  56. //   Sample Application Files which are modified.
  57. #include <windows.h>
  58. #include "showdib.h"
  59.  
  60. static HCURSOR hcurSave;
  61.  
  62. /****************************************************************************
  63.  *                                                                          *
  64.  *  FUNCTION   :OpenDIB(LPSTR szFile)                                       *
  65.  *                                                                          *
  66.  *  PURPOSE    :Open a DIB file and create a MEMORY DIB, a memory handle    *
  67.  *              containing BITMAPINFO, palette data and the bits.           *
  68.  *                                                                          *
  69.  *  RETURNS    :A handle to the DIB.                                        *
  70.  *                                                                          *
  71.  ****************************************************************************/
  72.  
  73.  
  74. HANDLE OpenDIB (szFile)
  75. LPSTR szFile;
  76. {
  77.    unsigned fh;
  78.    BITMAPINFOHEADER bi;
  79.    LPBITMAPINFOHEADER lpbi;
  80.    DWORD dwLen = 0;
  81.    DWORD dwBits;
  82.    HANDLE hdib;
  83.    HANDLE h;
  84.    OFSTRUCT of;
  85.  
  86.    /* Open the file and read the DIB information */
  87.  
  88.    fh = OpenFile(szFile, &of, OF_READ);
  89.    if (fh == -1)
  90.       return NULL;
  91.    hdib = ReadDibBitmapInfo(fh);
  92.    if (!hdib)
  93.       return NULL;
  94.    DibInfo(hdib, &bi);
  95.  
  96.    /* Calculate the memory needed to hold the DIB */
  97.    dwBits = bi.biSizeImage;
  98.    dwLen = bi.biSize + (DWORD)PaletteSize(&bi) + dwBits;
  99.  
  100.    /* Try to increase the size of the bitmap info. buffer to hold the DIB */
  101.    h = GlobalReAlloc(hdib, dwLen, GHND);
  102.    if (!h)
  103.    {
  104.       GlobalFree(hdib);
  105.       hdib = NULL;
  106.    }
  107.    else
  108.       hdib = h;
  109.  
  110.    /* Read in the bits */
  111.    if (hdib)
  112.    {
  113.       lpbi = (VOID FAR *)GlobalLock(hdib);
  114.       lread(fh, (LPSTR)lpbi + (WORD)lpbi->biSize + PaletteSize(lpbi), dwBits);
  115.       GlobalUnlock(hdib);
  116.    }
  117.    _lclose(fh);
  118.    return hdib;
  119. }
  120.  
  121. /****************************************************************************
  122.  *                                                                          *
  123.  *  FUNCTION   : WriteDIB(LPSTR szFile,HANDLE hdib)                         *
  124.  *                                                                          *
  125.  *  PURPOSE    : Write a global handle in CF_DIB format to a file.          *
  126.  *                                                                          *
  127.  *  RETURNS    : TRUE  - if successful.                                     *
  128.  *               FALSE - otherwise                                          *
  129.  *                                                                          *
  130.  ****************************************************************************/
  131.  
  132.  
  133. BOOL WriteDIB (szFile, hdib)
  134. LPSTR szFile;
  135. HANDLE hdib;
  136. {
  137.    BITMAPFILEHEADER hdr;
  138.    LPBITMAPINFOHEADER lpbi;
  139.    int fh;
  140.    OFSTRUCT of;
  141.  
  142.    if (!hdib)
  143.       return FALSE;
  144.    fh = OpenFile(szFile, &of, OF_CREATE | OF_READWRITE);
  145.    if (fh == -1)
  146.       return FALSE;
  147.    lpbi = (VOID FAR *)GlobalLock(hdib);
  148.  
  149.    /* Fill in the fields of the file header */
  150.    hdr.bfType = BFT_BITMAP;
  151.    hdr.bfSize = GlobalSize(hdib) + sizeof(BITMAPFILEHEADER);
  152.    hdr.bfReserved1 = 0;
  153.    hdr.bfReserved2 = 0;
  154.    hdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + lpbi->biSize + PaletteSize
  155.                    (lpbi);
  156.  
  157.    /* Write the file header */
  158.    _lwrite(fh, (LPSTR)&hdr, sizeof(BITMAPFILEHEADER));
  159.  
  160.    /* Write the DIB header and the bits */
  161.    lwrite(fh, (LPSTR)lpbi, GlobalSize(hdib));
  162.    GlobalUnlock(hdib);
  163.    _lclose(fh);
  164.    return TRUE;
  165. }
  166.  
  167. /****************************************************************************
  168.  *                                                                          *
  169.  *  FUNCTION   : DibInfo(HANDLE hbi,LPBITMAPINFOHEADER lpbi)                *
  170.  *                                                                          *
  171.  *  PURPOSE    : Retrieves the DIB info associated with a CF_DIB            *
  172.  *               format memory block.                                       *
  173.  *                                                                          *
  174.  *  RETURNS    : TRUE  - if successful.                                     *
  175.  *               FALSE - otherwise                                          *
  176.  *                                                                          *
  177.  ****************************************************************************/
  178.  
  179.  
  180. BOOL DibInfo (hbi, lpbi)
  181. HANDLE hbi;
  182. LPBITMAPINFOHEADER lpbi;
  183. {
  184.    if (hbi)
  185.    {
  186.       *lpbi = *(LPBITMAPINFOHEADER)GlobalLock(hbi);
  187.  
  188.       /* fill in the default fields */
  189.       if (lpbi->biSize != sizeof(BITMAPCOREHEADER))
  190.       {
  191.          if (lpbi->biSizeImage == 0L)
  192.             lpbi->biSizeImage = WIDTHBYTES(lpbi->biWidth*lpbi->biBitCount) *
  193.                                 lpbi->biHeight;
  194.          if (lpbi->biClrUsed == 0L)
  195.             lpbi->biClrUsed = DibNumColors(lpbi);
  196.       }
  197.       GlobalUnlock(hbi);
  198.       return TRUE;
  199.    }
  200.    return FALSE;
  201. }
  202.  
  203. /****************************************************************************
  204.  *                                                                          *
  205.  *  FUNCTION   : CreateBIPalette(LPBITMAPINFOHEADER lpbi)                   *
  206.  *                                                                          *
  207.  *  PURPOSE    : Given a Pointer to a BITMAPINFO struct will create a       *
  208.  *               a GDI palette object from the color table.                 *
  209.  *                                                                          *
  210.  *  RETURNS    : A handle to the palette.                                   *
  211.  *                                                                          *
  212.  ****************************************************************************/
  213.  
  214.  
  215. HPALETTE CreateBIPalette (lpbi)
  216. LPBITMAPINFOHEADER lpbi;
  217. {
  218.    LOGPALETTE *pPal;
  219.    HPALETTE hpal = NULL;
  220.    WORD nNumColors;
  221.    BYTE red;
  222.    BYTE green;
  223.    BYTE blue;
  224.    WORD i;
  225.    RGBQUAD FAR *pRgb;
  226.  
  227.    if (!lpbi)
  228.       return NULL;
  229.    if (lpbi->biSize != sizeof(BITMAPINFOHEADER))
  230.       return NULL;
  231.  
  232.    /* Get a pointer to the color table and the number of colors in it */
  233.    pRgb = (RGBQUAD FAR *)((LPSTR)lpbi + (WORD)lpbi->biSize);
  234.    nNumColors = DibNumColors(lpbi);
  235.    if (nNumColors)
  236.    {
  237.       /* Allocate for the logical palette structure */
  238.       pPal = (LOGPALETTE *)LocalAlloc(LPTR, sizeof(LOGPALETTE) + nNumColors *
  239.                                       sizeof(PALETTEENTRY));
  240.       if (!pPal)
  241.          return NULL;
  242.       pPal->palNumEntries = nNumColors;
  243.       pPal->palVersion = PALVERSION;
  244.  
  245.       /* Fill in the palette entries from the DIB color table and
  246.        * create a logical color palette.
  247.        */
  248.       for (i = 0; i < nNumColors; i++)
  249.       {
  250.          pPal->palPalEntry[i].peRed = pRgb[i].rgbRed;
  251.          pPal->palPalEntry[i].peGreen = pRgb[i].rgbGreen;
  252.          pPal->palPalEntry[i].peBlue = pRgb[i].rgbBlue;
  253.          pPal->palPalEntry[i].peFlags = (BYTE)0;
  254.       }
  255.       hpal = CreatePalette(pPal);
  256.       LocalFree((HANDLE)pPal);
  257.    }
  258.    else if (lpbi->biBitCount == 24)
  259.    {
  260.       /* A 24 bitcount DIB has no color table entries so, set the number of
  261.        * to the maximum value (256).
  262.        */
  263.       nNumColors = MAXPALETTE;
  264.       pPal = (LOGPALETTE *)LocalAlloc(LPTR, sizeof(LOGPALETTE) + nNumColors *
  265.                                       sizeof(PALETTEENTRY));
  266.       if (!pPal)
  267.          return NULL;
  268.       pPal->palNumEntries = nNumColors;
  269.       pPal->palVersion = PALVERSION;
  270.       red = green = blue = 0;
  271.  
  272.       /* Generate 256 (= 8*8*4) RGB combinations to fill the palette
  273.        * entries.
  274.        */
  275.       for (i = 0; i < pPal->palNumEntries; i++)
  276.       {
  277.          pPal->palPalEntry[i].peRed = red;
  278.          pPal->palPalEntry[i].peGreen = green;
  279.          pPal->palPalEntry[i].peBlue = blue;
  280.          pPal->palPalEntry[i].peFlags = (BYTE)0;
  281.          if (!(red += 32))
  282.             if (!(green += 32))
  283.                blue += 64;
  284.       }
  285.       hpal = CreatePalette(pPal);
  286.       LocalFree((HANDLE)pPal);
  287.    }
  288.    return hpal;
  289. }
  290.  
  291. /****************************************************************************
  292.  *                                                                          *
  293.  *  FUNCTION   : CreateDibPalette(HANDLE hbi)                               *
  294.  *                                                                          *
  295.  *  PURPOSE    : Given a Global HANDLE to a BITMAPINFO Struct               *
  296.  *               will create a GDI palette object from the color table.     *
  297.  *               (BITMAPINFOHEADER format DIBs only)                                     *
  298.  *                                                                          *
  299.  *  RETURNS    : A handle to the palette.                                   *
  300.  *                                                                          *
  301.  ****************************************************************************/
  302.  
  303.  
  304. HPALETTE CreateDibPalette (hbi)
  305. HANDLE hbi;
  306. {
  307.    HPALETTE hpal;
  308.  
  309.    if (!hbi)
  310.       return NULL;
  311.    hpal = CreateBIPalette((LPBITMAPINFOHEADER)GlobalLock(hbi));
  312.    GlobalUnlock(hbi);
  313.    return hpal;
  314. }
  315.  
  316. /****************************************************************************
  317.  *                                                                          *
  318.  *  FUNCTION   : ReadDibBitmapInfo(int fh)                                  *
  319.  *                                                                          *
  320.  *  PURPOSE    : Will read a file in DIB format and return a global HANDLE  *
  321.  *               to it's BITMAPINFO.  This function will work with both     *
  322.  *               "old" (BITMAPCOREHEADER) and "new" (BITMAPINFOHEADER)      *
  323.  *               bitmap formats, but will always return a "new" BITMAPINFO  *
  324.  *                                                                          *
  325.  *  RETURNS    : A handle to the BITMAPINFO of the DIB in the file.         *
  326.  *                                                                          *
  327.  ****************************************************************************/
  328.  
  329.  
  330. HANDLE ReadDibBitmapInfo (fh)
  331. int fh;
  332. {
  333.    DWORD off;
  334.    HANDLE hbi = NULL;
  335.    int size;
  336.    int i;
  337.    WORD nNumColors;
  338.    RGBQUAD FAR *pRgb;
  339.    BITMAPINFOHEADER bi;
  340.    BITMAPCOREHEADER bc;
  341.    LPBITMAPINFOHEADER lpbi;
  342.    BITMAPFILEHEADER bf;
  343.    DWORD dwWidth = 0;
  344.    DWORD dwHeight = 0;
  345.    WORD wPlanes, wBitCount;
  346.  
  347.    if (fh == -1)
  348.       return NULL;
  349.  
  350.    /* Reset file pointer and read file header */
  351.    off = _llseek(fh, 0L, SEEK_CUR);
  352.    if (sizeof(bf) != _lread(fh, (LPSTR)&bf, sizeof(bf)))
  353.       return FALSE;
  354.  
  355.    /* Do we have a RC HEADER? */
  356.    if (!ISDIB (bf.bfType))
  357.    {
  358.       bf.bfOffBits = 0L;
  359.       _llseek(fh, off, SEEK_SET);
  360.    }
  361.    if (sizeof(bi) != _lread(fh, (LPSTR)&bi, sizeof(bi)))
  362.       return FALSE;
  363.    nNumColors = DibNumColors(&bi);
  364.  
  365.    /* Check the nature (BITMAPINFO or BITMAPCORE) of the info. block
  366.     * and extract the field information accordingly. If a BITMAPCOREHEADER,
  367.     * transfer it's field information to a BITMAPINFOHEADER-style block
  368.     */
  369.    switch (size = (int)bi.biSize)
  370.       {
  371.    case sizeof(BITMAPINFOHEADER):
  372.       break;
  373.  
  374.    case sizeof(BITMAPCOREHEADER):
  375.       bc = *(BITMAPCOREHEADER *)&bi;
  376.       dwWidth = (DWORD)bc.bcWidth;
  377.       dwHeight = (DWORD)bc.bcHeight;
  378.       wPlanes = bc.bcPlanes;
  379.       wBitCount = bc.bcBitCount;
  380.       bi.biSize = sizeof(BITMAPINFOHEADER);
  381.       bi.biWidth = dwWidth;
  382.       bi.biHeight = dwHeight;
  383.       bi.biPlanes = wPlanes;
  384.       bi.biBitCount = wBitCount;
  385.       bi.biCompression = BI_RGB;
  386.       bi.biSizeImage = 0;
  387.       bi.biXPelsPerMeter = 0;
  388.       bi.biYPelsPerMeter = 0;
  389.       bi.biClrUsed = nNumColors;
  390.       bi.biClrImportant = nNumColors;
  391.       _llseek(fh, (LONG)sizeof(BITMAPCOREHEADER) - sizeof(BITMAPINFOHEADER),
  392.               SEEK_CUR);
  393.       break;
  394.  
  395.    default:
  396.       /* Not a DIB! */
  397.       return NULL;
  398.       }
  399.  
  400.    /*  Fill in some default values if they are zero */
  401.    if (bi.biSizeImage == 0)
  402.    {
  403.       bi.biSizeImage = WIDTHBYTES ((DWORD)bi.biWidth * bi.biBitCount) * bi.
  404.                        biHeight;
  405.    }
  406.    if (bi.biClrUsed == 0)
  407.       bi.biClrUsed = DibNumColors(&bi);
  408.  
  409.    /* Allocate for the BITMAPINFO structure and the color table. */
  410.    hbi = GlobalAlloc(GHND, (LONG)bi.biSize + nNumColors * sizeof(RGBQUAD));
  411.    if (!hbi)
  412.       return NULL;
  413.    lpbi = (VOID FAR *)GlobalLock(hbi);
  414.    *lpbi = bi;
  415.  
  416.    /* Get a pointer to the color table */
  417.    pRgb = (RGBQUAD FAR *)((LPSTR)lpbi + bi.biSize);
  418.    if (nNumColors)
  419.    {
  420.       if (size == sizeof(BITMAPCOREHEADER))
  421.       {
  422.          /* Convert a old color table (3 byte RGBTRIPLEs) to a new
  423.           * color table (4 byte RGBQUADs)
  424.           */
  425.          _lread(fh, (LPSTR)pRgb, nNumColors * sizeof(RGBTRIPLE));
  426.          for (i = nNumColors - 1; i >= 0; i--)
  427.          {
  428.             RGBQUAD rgb;
  429.  
  430.             rgb.rgbRed = ((RGBTRIPLE FAR *)pRgb)[i].rgbtRed;
  431.             rgb.rgbBlue = ((RGBTRIPLE FAR *)pRgb)[i].rgbtBlue;
  432.             rgb.rgbGreen = ((RGBTRIPLE FAR *)pRgb)[i].rgbtGreen;
  433.             rgb.rgbReserved = (BYTE)0;
  434.             pRgb[i] = rgb;
  435.          }
  436.       }
  437.       else
  438.          _lread(fh, (LPSTR)pRgb, nNumColors * sizeof(RGBQUAD));
  439.    }
  440.    if (bf.bfOffBits != 0L)
  441.       _llseek(fh, off + bf.bfOffBits, SEEK_SET);
  442.    GlobalUnlock(hbi);
  443.    return hbi;
  444. }
  445.  
  446. /****************************************************************************
  447.  *                                                                          *
  448.  *  FUNCTION   :  PaletteSize(VOID FAR * pv)                                *
  449.  *                                                                          *
  450.  *  PURPOSE    :  Calculates the palette size in bytes. If the info. block  *
  451.  *                is of the BITMAPCOREHEADER type, the number of colors is  *
  452.  *                multiplied by 3 to give the palette size, otherwise the   *
  453.  *                number of colors is multiplied by 4.                                                          *
  454.  *                                                                          *
  455.  *  RETURNS    :  Palette size in number of bytes.                          *
  456.  *                                                                          *
  457.  ****************************************************************************/
  458.  
  459.  
  460. WORD PaletteSize (pv)
  461. VOID FAR *pv;
  462. {
  463.    LPBITMAPINFOHEADER lpbi;
  464.    WORD NumColors;
  465.  
  466.    lpbi = (LPBITMAPINFOHEADER)pv;
  467.    NumColors = DibNumColors(lpbi);
  468.    if (lpbi->biSize == sizeof(BITMAPCOREHEADER))
  469.       return NumColors * sizeof(RGBTRIPLE);
  470.    else
  471.       return NumColors * sizeof(RGBQUAD);
  472. }
  473.  
  474. /****************************************************************************
  475.  *                                                                          *
  476.  *  FUNCTION   : DibNumColors(VOID FAR * pv)                                *
  477.  *                                                                          *
  478.  *  PURPOSE    : Determines the number of colors in the DIB by looking at   *
  479.  *               the BitCount filed in the info block.                      *
  480.  *                                                                          *
  481.  *  RETURNS    : The number of colors in the DIB.                           *
  482.  *                                                                          *
  483.  ****************************************************************************/
  484.  
  485.  
  486. WORD DibNumColors (pv)
  487. VOID FAR *pv;
  488. {
  489.    int bits;
  490.    LPBITMAPINFOHEADER lpbi;
  491.    LPBITMAPCOREHEADER lpbc;
  492.  
  493.    lpbi = ((LPBITMAPINFOHEADER)pv);
  494.    lpbc = ((LPBITMAPCOREHEADER)pv);
  495.  
  496.    /*  With the BITMAPINFO format headers, the size of the palette
  497.     *  is in biClrUsed, whereas in the BITMAPCORE - style headers, it
  498.     *  is dependent on the bits per pixel ( = 2 raised to the power of
  499.     *  bits/pixel).
  500.     */
  501.    if (lpbi->biSize != sizeof(BITMAPCOREHEADER))
  502.    {
  503.       if (lpbi->biClrUsed != 0)
  504.          return (WORD)lpbi->biClrUsed;
  505.       bits = lpbi->biBitCount;
  506.    }
  507.    else
  508.       bits = lpbc->bcBitCount;
  509.    switch (bits)
  510.       {
  511.    case 1:
  512.       return 2;
  513.  
  514.    case 4:
  515.       return 16;
  516.  
  517.    case 8:
  518.       return 256;
  519.  
  520.    default:
  521.       /* A 24 bitcount DIB has no color table */
  522.       return 0;
  523.       }
  524. }
  525. /****************************************************************************
  526.  *                                                                          *
  527.  *  FUNCTION   : DibFromBitmap()                                            *
  528.  *                                                                          *
  529.  *  PURPOSE    : Will create a global memory block in DIB format that       *
  530.  *               represents the Device-dependent bitmap (DDB) passed in.    *
  531.  *                                                                          *
  532.  *  RETURNS    : A handle to the DIB                                        *
  533.  *                                                                          *
  534.  ****************************************************************************/
  535.  
  536.  
  537. HANDLE DibFromBitmap (hbm, biStyle, biBits, hpal)
  538. HBITMAP hbm;
  539. DWORD biStyle;
  540. WORD biBits;
  541. HPALETTE hpal;
  542. {
  543.    BITMAP bm;
  544.    BITMAPINFOHEADER bi;
  545.    BITMAPINFOHEADER FAR *lpbi;
  546.    DWORD dwLen;
  547.    HANDLE hdib;
  548.    HANDLE h;
  549.    HDC hdc;
  550.  
  551.    if (!hbm)
  552.       return NULL;
  553.    if (hpal == NULL)
  554.       hpal = GetStockObject(DEFAULT_PALETTE);
  555.    GetObject(hbm, sizeof(bm), (LPSTR)&bm);
  556.    if (biBits == 0)
  557.       biBits = bm.bmPlanes * bm.bmBitsPixel;
  558.    bi.biSize = sizeof(BITMAPINFOHEADER);
  559.    bi.biWidth = bm.bmWidth;
  560.    bi.biHeight = bm.bmHeight;
  561.    bi.biPlanes = 1;
  562.    bi.biBitCount = biBits;
  563.    bi.biCompression = biStyle;
  564.    bi.biSizeImage = 0;
  565.    bi.biXPelsPerMeter = 0;
  566.    bi.biYPelsPerMeter = 0;
  567.    bi.biClrUsed = 0;
  568.    bi.biClrImportant = 0;
  569.    dwLen = bi.biSize + PaletteSize(&bi);
  570.    hdc = GetDC(NULL);
  571.    hpal = SelectPalette(hdc, hpal, FALSE);
  572.    RealizePalette(hdc);
  573.    hdib = GlobalAlloc(GHND, dwLen);
  574.    if (!hdib)
  575.    {
  576.       SelectPalette(hdc, hpal, FALSE);
  577.       ReleaseDC(NULL, hdc);
  578.       return NULL;
  579.    }
  580.    lpbi = (VOID FAR *)GlobalLock(hdib);
  581.    *lpbi = bi;
  582.  
  583.    /*  call GetDIBits with a NULL lpBits param, so it will calculate the
  584.     *  biSizeImage field for us
  585.     */
  586.    GetDIBits(hdc, hbm, 0, (WORD)bi.biHeight, NULL, (LPBITMAPINFO)lpbi,
  587.              DIB_RGB_COLORS);
  588.    bi = *lpbi;
  589.    GlobalUnlock(hdib);
  590.  
  591.    /* If the driver did not fill in the biSizeImage field, make one up */
  592.    if (bi.biSizeImage == 0)
  593.    {
  594.       bi.biSizeImage = WIDTHBYTES((DWORD)bm.bmWidth * biBits) * bm.bmHeight;
  595.       if (biStyle != BI_RGB)
  596.          bi.biSizeImage = (bi.biSizeImage * 3) / 2;
  597.    }
  598.  
  599.    /*  realloc the buffer big enough to hold all the bits */
  600.    dwLen = bi.biSize + PaletteSize(&bi) + bi.biSizeImage;
  601.    if (h = GlobalReAlloc(hdib, dwLen, 0))
  602.       hdib = h;
  603.    else
  604.    {
  605.       GlobalFree(hdib);
  606.       hdib = NULL;
  607.       SelectPalette(hdc, hpal, FALSE);
  608.       ReleaseDC(NULL, hdc);
  609.       return hdib;
  610.    }
  611.  
  612.    /*  call GetDIBits with a NON-NULL lpBits param, and actualy get the
  613.     *  bits this time
  614.     */
  615.    lpbi = (VOID FAR *)GlobalLock(hdib);
  616.    if (GetDIBits(hdc, hbm, 0, (WORD)bi.biHeight, (LPSTR)lpbi + (WORD)lpbi->
  617.                  biSize + PaletteSize(lpbi), (LPBITMAPINFO)lpbi, DIB_RGB_COLORS
  618.                  ) == 0)
  619.    {
  620.       GlobalUnlock(hdib);
  621.       hdib = NULL;
  622.       SelectPalette(hdc, hpal, FALSE);
  623.       ReleaseDC(NULL, hdc);
  624.       return NULL;
  625.    }
  626.    bi = *lpbi;
  627.    GlobalUnlock(hdib);
  628.    SelectPalette(hdc, hpal, FALSE);
  629.    ReleaseDC(NULL, hdc);
  630.    return hdib;
  631. }
  632.  
  633. /****************************************************************************
  634.  *                                                                          *
  635.  *  FUNCTION   : BitmapFromDib(HANDLE hdib, HPALETTE hpal)                  *
  636.  *                                                                          *
  637.  *  PURPOSE    : Will create a DDB (Device Dependent Bitmap) given a global *
  638.  *               handle to a memory block in CF_DIB format                  *
  639.  *                                                                          *
  640.  *  RETURNS    : A handle to the DDB.                                       *
  641.  *                                                                          *
  642.  ****************************************************************************/
  643.  
  644.  
  645. HBITMAP BitmapFromDib (hdib, hpal)
  646. HANDLE hdib;
  647. HPALETTE hpal;
  648. {
  649.    LPBITMAPINFOHEADER lpbi;
  650.    HPALETTE hpalT;
  651.    HDC hdc;
  652.    HBITMAP hbm;
  653.  
  654.    StartWait();
  655.    if (!hdib)
  656.       return NULL;
  657.    lpbi = (VOID FAR *)GlobalLock(hdib);
  658.    if (!lpbi)
  659.       return NULL;
  660.    hdc = GetDC(NULL);
  661.    if (hpal)
  662.    {
  663.       hpalT = SelectPalette(hdc, hpal, FALSE);
  664.       RealizePalette(hdc);     // GDI Bug...????
  665.    }
  666.    hbm = CreateDIBitmap(hdc, (LPBITMAPINFOHEADER)lpbi, (LONG)CBM_INIT, (LPSTR)
  667.                         lpbi + lpbi->biSize + PaletteSize(lpbi), (LPBITMAPINFO)
  668.                         lpbi, DIB_RGB_COLORS);
  669.    if (hpal)
  670.       SelectPalette(hdc, hpalT, FALSE);
  671.    ReleaseDC(NULL, hdc);
  672.    GlobalUnlock(hdib);
  673.    EndWait();
  674.    return hbm;
  675. }
  676. /****************************************************************************
  677.  *                                                                          *
  678.  *  FUNCTION   : DrawBitmap(HDC hdc, int x, int y, HBITMAP hbm, DWORD rop)  *
  679.  *                                                                          *
  680.  *  PURPOSE    : Draws bitmap <hbm> at the specifed position in DC <hdc>    *
  681.  *                                                                          *
  682.  *  RETURNS    : Return value of BitBlt()                                   *
  683.  *                                                                          *
  684.  ****************************************************************************/
  685.  
  686.  
  687. BOOL DrawBitmap (hdc, x, y, hbm, rop)
  688. HDC hdc;
  689. int x, y;
  690. HBITMAP hbm;
  691. DWORD rop;
  692. {
  693.    HDC hdcBits;
  694.    BITMAP bm;
  695.    BOOL f;
  696.  
  697.    if (!hdc || !hbm)
  698.       return FALSE;
  699.    hdcBits = CreateCompatibleDC(hdc);
  700.    GetObject(hbm, sizeof(BITMAP), (LPSTR)&bm);
  701.    SelectObject(hdcBits, hbm);
  702.    f = BitBlt(hdc, 0, 0, bm.bmWidth, bm.bmHeight, hdcBits, 0, 0, rop);
  703.    DeleteDC(hdcBits);
  704.    return f;
  705. }
  706. /****************************************************************************
  707.  *                                                                          *
  708.  *  FUNCTION   : DibBlt( HDC hdc,                                           *
  709.  *                       int x0, int y0,                                    *
  710.  *                       int dx, int dy,                                    *
  711.  *                       HANDLE hdib,                                       *
  712.  *                       int x1, int y1,                                    *
  713.  *                       LONG rop)                                          *
  714.  *                                                                          *
  715.  *  PURPOSE    : Draws a bitmap in CF_DIB format, using SetDIBits to device.*
  716.  *               taking the same parameters as BitBlt().                    *
  717.  *                                                                          *
  718.  *  RETURNS    : TRUE  - if function succeeds.                              *
  719.  *               FALSE - otherwise.                                         *
  720.  *                                                                          *
  721.  ****************************************************************************/
  722.  
  723.  
  724. BOOL DibBlt (hdc, x0, y0, dx, dy, hdib, x1, y1, rop)
  725. HDC hdc;
  726. int x0, y0, dx, dy;
  727. HANDLE hdib;
  728. int x1, y1;
  729. LONG rop;
  730. {
  731.    LPBITMAPINFOHEADER lpbi;
  732.    LPSTR pBuf;
  733.  
  734.    if (!hdib)
  735.       return PatBlt(hdc, x0, y0, dx, dy, rop);
  736.    lpbi = (VOID FAR *)GlobalLock(hdib);
  737.    if (!lpbi)
  738.       return FALSE;
  739.    pBuf = (LPSTR)lpbi + (WORD)lpbi->biSize + PaletteSize(lpbi);
  740.    SetDIBitsToDevice(hdc, x0, y0, dx, dy, x1, y1, x1, dy, pBuf, (LPBITMAPINFO)
  741.                      lpbi, DIB_RGB_COLORS);
  742.    GlobalUnlock(hdib);
  743.    return TRUE;
  744. }
  745. /****************************************************************************
  746.  *                                                                          *
  747.  *  FUNCTION   : StretchDibBlt( HDC hdc,                                    *
  748.  *                              int x, int y,                               *
  749.  *                              int dx, int dy,                             *
  750.  *                              HANDLE hdib,                                *
  751.  *                              int x0, int y0,                             *
  752.  *                              int dx0, int dy0,                           *
  753.  *                              LONG rop)                                   *
  754.  *                                                                          *
  755.  *  PURPOSE    : Draws a bitmap in CF_DIB format, using StretchDIBits()     *
  756.  *               taking the same parameters as StretchBlt().                *
  757.  *                                                                          *
  758.  *  RETURNS    : TRUE  - if function succeeds.                              *
  759.  *               FALSE - otherwise.                                         *
  760.  *                                                                          *
  761.  ****************************************************************************/
  762.  
  763.  
  764. BOOL StretchDibBlt (hdc, x, y, dx, dy, hdib, x0, y0, dx0, dy0, rop)
  765. HDC hdc;
  766. int x, y;
  767. int dx, dy;
  768. HANDLE hdib;
  769. int x0, y0;
  770. int dx0, dy0;
  771. LONG rop;
  772. {
  773.    LPBITMAPINFOHEADER lpbi;
  774.    LPSTR pBuf;
  775.    BOOL f;
  776.  
  777.    if (!hdib)
  778.       return PatBlt(hdc, x, y, dx, dy, rop);
  779.    lpbi = (VOID FAR *)GlobalLock(hdib);
  780.    if (!lpbi)
  781.       return FALSE;
  782.    pBuf = (LPSTR)lpbi + (WORD)lpbi->biSize + PaletteSize(lpbi);
  783.    f = StretchDIBits(hdc, x, y, dx, dy, x0, y0, dx0, dy0, pBuf, (LPBITMAPINFO)
  784.                      lpbi, DIB_RGB_COLORS, rop);
  785.    GlobalUnlock(hdib);
  786.    return f;
  787. }
  788.  
  789. /************* PRIVATE ROUTINES TO READ/WRITE MORE THAN 64K ***************/
  790. /****************************************************************************
  791.  *                                                                          *
  792.  *  FUNCTION   : lread(int fh, VOID FAR *pv, DWORD ul)                      *
  793.  *                                                                          *
  794.  *  PURPOSE    : Reads data in steps of 32k till all the data has been read.*
  795.  *                                                                          *
  796.  *  RETURNS    : 0 - If read did not proceed correctly.                     *
  797.  *               number of bytes read otherwise.                            *
  798.  *                                                                          *
  799.  ****************************************************************************/
  800.  
  801.  
  802. DWORD PASCAL lread (fh, pv, ul)
  803. int fh;
  804. VOID far *pv;
  805. DWORD ul;
  806. {
  807.    DWORD ulT = ul;
  808.    BYTE huge *hp = pv;
  809.  
  810.    while (ul > (DWORD)MAXREAD)
  811.    {
  812.       if (_lread(fh, (LPSTR)hp, (WORD)MAXREAD) != MAXREAD)
  813.          return 0;
  814.       ul -= MAXREAD;
  815.       hp += MAXREAD;
  816.    }
  817.    if (_lread(fh, (LPSTR)hp, (WORD)ul) != (WORD)ul)
  818.       return 0;
  819.    return ulT;
  820. }
  821.  
  822. /****************************************************************************
  823.  *                                                                          *
  824.  *  FUNCTION   : lwrite(int fh, VOID FAR *pv, DWORD ul)                     *
  825.  *                                                                          *
  826.  *  PURPOSE    : Writes data in steps of 32k till all the data is written.  *
  827.  *                                                                          *
  828.  *  RETURNS    : 0 - If write did not proceed correctly.                    *
  829.  *               number of bytes written otherwise.                         *
  830.  *                                                                          *
  831.  ****************************************************************************/
  832.  
  833.  
  834. DWORD PASCAL lwrite (fh, pv, ul)
  835. int fh;
  836. VOID FAR *pv;
  837. DWORD ul;
  838. {
  839.    DWORD ulT = ul;
  840.    BYTE huge *hp = pv;
  841.  
  842.    while (ul > MAXREAD)
  843.    {
  844.       if (_lwrite(fh, (LPSTR)hp, (WORD)MAXREAD) != MAXREAD)
  845.          return 0;
  846.       ul -= MAXREAD;
  847.       hp += MAXREAD;
  848.    }
  849.    if (_lwrite(fh, (LPSTR)hp, (WORD)ul) != (WORD)ul)
  850.       return 0;
  851.    return ulT;
  852. }
  853.